﻿using System;
using System.Collections.Generic;
using System.Linq;
using Xenta.Entities;
using Xenta.Enums;
using Xenta.Security;
using Xenta.Utils;

namespace Xenta.Operations
{
    public class ImportStockEntries : ImportOperation,
        ISecuredOperation
    {
        #region Properties

        public IEnumerable<SecurityPolicy> SecurityPolicies
        {
            get
            {
                yield return new SecurityPolicy()
                    .IsAuthenticated()
                    .HasPermission("SALES");
            }
        }

        #endregion

        #region Utilities

        protected override void Work(IUnitOfWork uow, out int result)
        {
            result = 0;
            foreach(var i in Objects)
            {
                if(!i.ContainsKey("ItemID") ||
                    !i.ContainsKey("AdjustmentMin") ||
                    !i.ContainsKey("AdjustmentMax") ||
                    !i.ContainsKey("Reserve") ||
                    !i.ContainsKey("ExhaustionThreshold") ||
                    !i.ContainsKey("Flags"))
                {
                    continue;
                }

                int itemID = i["ItemID"].ParseAs(0);
                decimal adjustmentMin = i["AdjustmentMin"].ParseAs(Decimal.Zero);
                decimal adjustmentMax = i["AdjustmentMax"].ParseAs(Decimal.Zero);
                decimal reserve = i["Reserve"].ParseAs(Decimal.Zero);
                decimal exhaustionThreshold = i["ExhaustionThreshold"].ParseAs(Decimal.Zero);
                var flags = i["Flags"].ParseAs<StockEntryFlags>();

                uow.Execute(new SetStockEntry
                {
                    ItemID = itemID,
                    AdjustmentMin = adjustmentMin,
                    AdjustmentMax = adjustmentMax,
                    Reserve = reserve,
                    ExhaustionThreshold = exhaustionThreshold,
                    Flags = flags
                });
                result++;
            }
        }

        #endregion
    }

    public class ImportSalesOptions : ImportOperation,
        ISecuredOperation
    {
        #region Properties

        public IEnumerable<SecurityPolicy> SecurityPolicies
        {
            get
            {
                yield return new SecurityPolicy()
                    .IsAuthenticated()
                    .HasPermission("SALES");
            }
        }

        #endregion

        #region Utilities

        protected override void Work(IUnitOfWork uow, out int result)
        {
            result = 0;
            var languages = uow.Execute(new SearchLanguages()).Result;
            foreach(var i in Objects)
            {
                if(!i.ContainsKey("EntityID") ||
                    !i.ContainsKey("Price") ||
                    !i.ContainsKey("Code") ||
                    !i.ContainsKey("Flags"))
                {
                    continue;
                }

                int entityID = i["EntityID"].ParseAs(0);
                decimal price = i["Price"].ParseAs(Decimal.Zero);
                string code = i["Code"];
                var flags = i["Flags"].ParseAs<SalesOptionFlags>();
                SalesOptionEntity entity = null;
                var codeNameValue = code.Split(new[] { ':' }, 2);
                if(codeNameValue.Length != 2)
                    continue;

                if(entityID != 0)
                {
                    entity = uow.Execute(new UpdateSalesOption
                    {
                        EntityID = entityID,
                        Price = price,
                        CodeName = codeNameValue[0],
                        CodeValue = codeNameValue[1],
                        Flags = flags
                    }).Result;
                }
                else
                {
                    entity = uow.Execute(new CreateSalesOption
                    {
                        Price = price,
                        CodeName = codeNameValue[0],
                        CodeValue = codeNameValue[1],
                        Flags = flags
                    }).Result;
                }

                foreach(var l in languages.Where(x => i.ContainsKey(x.Code)))
                {
                    string tmp = i[l.Code];
                    if(String.IsNullOrWhiteSpace(tmp))
                        continue;

                    var nv = tmp.Split(new[] { ':' }, 2);
                    if(nv.Length != 2)
                        continue;

                    uow.Execute(new SaveSalesOptionTranslation
                    {
                        HolderID = entity.EntityID,
                        LanguageID = l.EntityID,
                        Name = nv[0],
                        Value = nv[1]
                    });
                }

                result++;
            }
        }

        #endregion
    }

    public class ImportSalesItems : ImportOperation,
        ISecuredOperation
    {
        #region Properties

        public IEnumerable<SecurityPolicy> SecurityPolicies
        {
            get
            {
                yield return new SecurityPolicy()
                    .IsAuthenticated()
                    .HasPermission("SALES");
            }
        }

        #endregion

        #region Utilities

        protected override void Work(IUnitOfWork uow, out int result)
        {
            result = 0;
            foreach(var i in Objects)
            {
                if(!i.ContainsKey("EntityID") ||
                    !i.ContainsKey("SKU") ||
                    !i.ContainsKey("SellerID") ||
                    !i.ContainsKey("CatalogItemID") ||
                    !i.ContainsKey("Price") ||
                    !i.ContainsKey("Rules") ||
                    !i.ContainsKey("Options") ||
                    !i.ContainsKey("AvailableFrom") ||
                    !i.ContainsKey("AvailableTo") ||
                    !i.ContainsKey("Flags"))
                {
                    continue;
                }

                int entityID = i["EntityID"].ParseAs(0);
                string sku = i["SKU"];
                int sellerID = i["SellerID"].ParseAs(0);
                int catalogItemID = i["CatalogItemID"].ParseAs(0);
                decimal price = i["Price"].ParseAs(Decimal.Zero);
                var ruleIDs = i["Rules"].Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries)
                    .Select(x => x.ParseAs<Int32>());
                var optionIDs = i["Options"].Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries)
                    .Select(x => x.ParseAs<Int32>());
                var availableFrom = i["AvailableFrom"].ParseAs(DateTime.UtcNow);
                var availableTo = i["AvailableTo"].ParseAs(DateTime.UtcNow);
                var flags = i["Flags"].ParseAs<SalesItemFlags>();
                var entity = entityID == 0 ? null : uow.Execute(new GetSalesItem
                {
                    EntityID = entityID
                }).Result;

                if(entity != null)
                {
                    entity = uow.Execute(new UpdateSalesItem
                    {
                        EntityID = entity.EntityID,
                        CatalogItemID = catalogItemID,
                        SellerID = sellerID,
                        SKU = sku,
                        Price = price,
                        AvailableFrom = availableFrom,
                        AvailableTo = availableTo,
                        Flags = flags
                    }).Result;
                }
                else
                {
                    entity = uow.Execute(new CreateSalesItem
                    {
                        CatalogItemID = catalogItemID,
                        SellerID = sellerID,
                        SKU = sku,
                        Price = price,
                        AvailableFrom = availableFrom,
                        AvailableTo = availableTo,
                        Flags = flags
                    }).Result;
                }

                var oldRuleIDs = entity.Rules
                    .Select(x => x.EntityID).ToList();
                foreach(var j in oldRuleIDs.Except(ruleIDs))
                {
                    uow.Execute(new UnmapSalesRuleFromSalesItem
                    {
                        EntityID = entity.EntityID,
                        ChildID = j
                    });
                }
                foreach(var j in ruleIDs.Except(oldRuleIDs))
                {
                    uow.Execute(new MapSalesRuleToSalesItem
                    {
                        EntityID = entity.EntityID,
                        ChildID = j
                    });
                }

                var oldOptionIDs = entity.Options
                    .Select(x => x.EntityID).ToList();
                foreach(var j in oldOptionIDs.Except(optionIDs))
                {
                    uow.Execute(new UnmapSalesOptionFromSalesItem
                    {
                        EntityID = entity.EntityID,
                        ChildID = j
                    });
                }
                foreach(var j in optionIDs.Except(oldOptionIDs))
                {
                    uow.Execute(new MapSalesOptionToSalesItem
                    {
                        EntityID = entity.EntityID,
                        ChildID = j
                    });
                }

                result++;
            }
        }

        #endregion
    }
}
